C# 自定义特性Attribute与反射调用 |
您所在的位置:网站首页 › unity 反射调用方法 › C# 自定义特性Attribute与反射调用 |
C# 自定义特性Attribute与反射调用
前言1.AttributeUtil.cs2.两个打印任务类(1)PrintTaskA.cs(2)PrintTaskB.cs
3.Program.cs
前言
👨💻👨🌾📝记录学习成果,以便温故而知新
一个项目有对个打印任务,每个打印任务调用不同的Excel模板进行打印。利用自定义特性PrintTaskAttribute来标识打印任务函数,再利用反射的方法把打印任务名与打印方法的映射关系存到字典里。以下是把项目中的思路抽出来整了个演示项目。 项目结构如下: 1.AttributeUtil.cs文件中含AttributeUtil(特性工具类)、PrintTaskAttribute(打印任务特性)与ObjectMethodInfo(特性内容与映射方法类)。AttributeUtil工具类有MapPrintTaskToMethod与InvokePrintTask两个方法,MapPrintTaskToMethod方法映射程序集中所有含打印任务特性的方法,InvokePrintTask调用映射的打印任务方法。 namespace Print { /// /// 特性工具类 /// author: Antonio /// class AttributeUtil { /// /// 打印任务映射处理方法 /// author: Antonio /// /// 打印任务与调用方法映射字典 /// 程序集 public void MapPrintTaskToMethod(out Dictionary objectMethodDictionary, string assemblyName) { objectMethodDictionary = new Dictionary(); Assembly assembly = Assembly.Load(assemblyName); Type[] types = assembly.GetTypes(); foreach (Type t in types) { object _Object = null; //Debug.WriteLine(t.FullName, "类名"); MethodInfo[] methodInfos = t.GetMethods(); foreach (MethodInfo methodInfo in methodInfos) { //Debug.WriteLine(methodInfo.Name, "方法名"); IEnumerable attributes = methodInfo.GetCustomAttributes(); foreach (Attribute attr in attributes) { //Debug.WriteLine(attr.ToString(), "特性"); if (attr is PrintTaskAttribute) { PrintTaskAttribute printTaskAttribute = (PrintTaskAttribute)attr; string printTaskName = printTaskAttribute.printTaskName; //Debug.WriteLine(printTaskName, "PrintTaskName"); if (!objectMethodDictionary.ContainsKey(printTaskName)) { ObjectMethodInfo objectMethod = new ObjectMethodInfo(); if (_Object == null) { _Object = Activator.CreateInstance(t); } objectMethod._Object = _Object;//类 objectMethod._MethodInfo = methodInfo;//方法 objectMethodDictionary[printTaskName] = objectMethod; } else { Debug.Fail(t.FullName + "." + methodInfo.Name + "[" + printTaskAttribute.TypeId + "(PrintTaskName)]:" + printTaskName + "已存在"); } } } } } } /// /// 调用打印任务 /// author: Antonio /// /// 打印任务与调用方法映射字典 /// 打印任务 /// 参数 /// public bool InvokePrintTask(Dictionary objectMethodDictionary, string printTaskName, Dictionary dic) { bool b = false; if (objectMethodDictionary.ContainsKey(printTaskName)) { object o = objectMethodDictionary[printTaskName]._MethodInfo.Invoke(objectMethodDictionary[printTaskName]._Object, new object[] { dic }); b = (bool)o; } return b; } } /// /// 打印任务特性 /// author: Antonio /// [AttributeUsage(AttributeTargets.Method)] public class PrintTaskAttribute : Attribute { public string printTaskName { get; set; } public PrintTaskAttribute(string printTaskName) { this.printTaskName = printTaskName; } } /// /// 特性内容与映射方法类 /// author: Antonio /// public class ObjectMethodInfo { /// /// 类 /// public object _Object { get; set; } /// /// 类方法 /// public MethodInfo _MethodInfo { get; set; } } }核心代码: object o = objectMethodDictionary[printTaskName]._MethodInfo.Invoke(objectMethodDictionary[printTaskName]._Object, new object[] { dic });objectMethodDictionary[printTaskName]._MethodInfo是调用的方法。 参数objectMethodDictionary[printTaskName]._Object是方法所属对象。 new object[] { dic }是传参。 2.两个打印任务类 (1)PrintTaskA.cs模拟打印任务A下有个模板 namespace Print { /// /// 打印任务A /// author: Antonio /// class PrintTaskA { /// /// 任务A-模板1 /// author: Antonio /// /// 参数 /// [PrintTask("任务A-模板1")] public bool Task_A_1(Dictionary dic) { Console.WriteLine("===任务A-模板1==="); Console.WriteLine("姓名:" + dic["name"]); Console.WriteLine("年龄" + dic["age"]); return true; } /// /// 任务A-模板2 /// author: Antonio /// /// 参数 /// [PrintTask("任务A-模板2")] public bool Task_A_2(Dictionary dic) { Console.WriteLine("===任务A-模板2==="); Console.Write("姓名:" + dic["name"]); Console.Write(" "); Console.WriteLine("年龄" + dic["age"]); return true; } } } (2)PrintTaskB.cs模拟打印任务B下有3个模板 namespace Print { /// /// 打印任务B /// author: Antonio /// class PrintTaskB { /// /// 任务B-模板1 /// author: Antonio /// /// 参数 /// [PrintTask("任务B-模板1")] public bool Task_B_1(Dictionary dic) { Console.WriteLine("===任务B-模板1==="); Console.WriteLine(dic["Tom"] + "和" +dic["Jerry"] + "一起工作"); return true; } /// /// 任务B-模板2 /// author: Antonio /// /// 参数 /// [PrintTask("任务B-模板2")] public bool Task_B_2(Dictionary dic) { Console.WriteLine("===任务B-模板1==="); Console.WriteLine(dic["Tom"] + "帮助" + dic["Jerry"] ); return true; } /// /// 任务B-模板3 /// author: Antonio /// /// 参数 /// [PrintTask("任务B-模板3")] public bool Task_B_3(Dictionary dic) { Console.WriteLine("===任务B-模板1==="); Console.WriteLine(dic["Jerry"] + "帮助" + dic["Tom"]); return true; } } } 3.Program.cs演示效果代码如下: namespace Print { class Program { static void Main(string[] args) { Dictionary objectMethodDictionary = new Dictionary(); AttributeUtil util = new AttributeUtil(); //程序集Print中打印任务映射处理方法 util.MapPrintTaskToMethod(out objectMethodDictionary, "Print"); Dictionary dic1 = new Dictionary(); dic1["name"] = "Tom"; dic1["age"] = 18; util.InvokePrintTask(objectMethodDictionary, "任务A-模板1", dic1);//调用任务A-模板1 util.InvokePrintTask(objectMethodDictionary, "任务A-模板2", dic1);//调用任务A-模板3 Dictionary dic2 = new Dictionary(); dic2["Tom"] = "Tom"; dic2["Jerry"] = "Jerry"; util.InvokePrintTask(objectMethodDictionary, "任务B-模板1", dic2);//调用任务B-模板1 util.InvokePrintTask(objectMethodDictionary, "任务B-模板2", dic2);//调用任务B-模板2 util.InvokePrintTask(objectMethodDictionary, "任务B-模板3", dic2);//调用任务B-模板3 Console.Read(); } } }在实际项目中调用打印任务,打印任务名一般是以动态参数形式传入,dic参数应与打印任务匹配,这样的话如果有新的打印任务,只需新增打印任务功能方法,其它代码可以少改,甚至不需改动。 |
今日新闻 |
推荐新闻 |
CopyRight 2018-2019 办公设备维修网 版权所有 豫ICP备15022753号-3 |